﻿package com.bizmlib.framework.abstract.mvc
{
	/**
	 * Controller implementation.
	 * @author	Valentyn Derkach
	 */
	import flash.events.EventDispatcher;
	
	import com.bizmlib.framework.abstract.mvc.*;
	import com.bizmlib.framework.abstract.commands.AbstractCommand;
	
	
	public class AbstractController extends EventDispatcher
	{
		private var __view:AbstractView;
	
	
		public function AbstractController(view:AbstractView)
		{
			if(!view){
				throw new Error(this + " initialization failed: no reference to a AbstractView instance was provided");
				return;
			}
			
			__view = view;
			
			init();
		}
	
	
		/**
		 * Returns a reference to a view. Read only.
		 */
		public function get view():AbstractView
		{
			return __view;
		}
		/**
		 * Returns a reference to a model. Read only.
		 */
		public function get model():AbstractModel
		{
			return view.model;
		}
		
		
		/**
		 * Performes a cleanning routine, so that a instance gets ready to be destroyed and collected by a 
		 * garbage collector.
		 */
		public function clean():void
		{
			var model:AbstractModel = this.model;
			
			if(model)
			{
				unsubscribeFromModelEvents();
			}
			
			if(view)
			{
				unsubscribeFromViewEvents();
				if(view.parent)
				{
					view.parent.removeChild(view);
				}
				view.clean();
				__view = null;
			}
			
			if(model)
			{
				model.clean();
			}
		}
		
		
		/**
		 * Does an initialization stuff. Feel free to override.
		 */
		protected function init():void
		{
			beforeInit();
			
			subscribeToViewEvents();
			subscribeToModelEvents();
			
			afterInit();
		}
		protected function beforeInit():void
		{
		}
		protected function afterInit():void
		{
		}
		/**
		 * Subscribes to listen view events here. Invoked from init before a afterInit call.
		 */
		protected function subscribeToViewEvents():void
		{
		}
		/**
		 * Unsubscribes from listening a view events. Invoked from a clean method.
		 */
		protected function unsubscribeFromViewEvents():void
		{
		}
		/**
		 * Subscribes to listen view events here. Invoked from init before a afterInit call.
		 */
		protected function subscribeToModelEvents():void
		{
		}
		/**
		 * Unsubscribes from listening a model events. Invoked from a clean method.
		 */
		protected function unsubscribeFromModelEvents():void
		{
		}
		
		protected function instantiateCommand(commandClass:Class, launch:Boolean = false):AbstractCommand
		{
			var command:AbstractCommand = new commandClass() as AbstractCommand;
			
			command.setMVC(model, view, this);
			
			if(launch)
			{
				command.launch();
			}
			
			return command;
		}
	
	
		/**
		 * Returns a string describing an nstance.
		 */
		override public function toString():String
		{
			return "[com.bizmlib.framework.abstract.mvc.AbstractController]";
		}
	
	}
}